package com.uinnova.product.eam.service.asset.impl;

import com.alibaba.fastjson.JSON;
import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.uinnova.product.cj.feign.dto.PlanDesignInstanceDTO;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.bean.EamConfiguration;
import com.uinnova.product.eam.comm.model.es.AppPanoramaInfo;
import com.uinnova.product.eam.config.Env;
import com.uinnova.product.eam.model.*;
import com.uinnova.product.eam.model.vo.*;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.eam.service.asset.AppSystemSvc;
import com.uinnova.product.eam.service.asset.AssetContent;
import com.uinnova.product.eam.service.asset.BmConfigSvc;
import com.uinnova.product.eam.service.cj.service.PlanDesignInstanceService;
import com.uinnova.product.eam.service.es.IamsESCIDesignSvc;
import com.uinnova.product.eam.service.es.IamsESCIPrivateSvc;
import com.uinnova.product.eam.service.es.IamsEamConfigurationDao;
import com.uinnova.product.vmdb.comm.model.ci.CCcCi;
import com.uinnova.product.vmdb.comm.model.ci.CCcCiClass;
import com.uinnova.product.vmdb.comm.model.ci.CcCiAttrDef;
import com.uinnova.product.vmdb.comm.model.ci.CcCiClass;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiInfo;
import com.uinnova.product.vmdb.provider.rlt.bean.CcCiRltInfo;
import com.uino.bean.cmdb.base.ESCIAttrDefInfo;
import com.uino.bean.cmdb.base.ESCIClassInfo;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.cmdb.query.ClsAttrQueryGroup;
import com.uino.bean.cmdb.query.ESAttrBean;
import com.uino.bean.cmdb.query.ESCISearchBean;
import com.uino.bean.cmdb.query.ESRltSearchBean;
import com.uino.bean.sys.base.ESDictionaryAttrDef;
import com.uino.bean.sys.base.ESDictionaryClassInfo;
import com.uino.bean.sys.base.ESDictionaryItemInfo;
import com.uino.dao.cmdb.CiClassProDropSourceDefHelper;
import com.uino.dao.cmdb.ESCIClassSvc;
import com.uino.dao.sys.ESDictionaryClassSvc;
import com.uino.dao.sys.ESDictionaryItemSvc;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.BeanUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class AppSystemSvcImpl implements AppSystemSvc, AssetContent {

    @Resource
    IamsESCIDesignSvc iamsESCIDesignSvc;

    @Resource
    IamsESCIPrivateSvc iamsESCIPrivateSvc;

    @Resource
    ICISwitchSvc ciSwitchSvc;
    @Resource
    ESCIClassSvc classSvc;

    @Resource
    IamsEamConfigurationDao iamsEamConfigurationDao;

    @Resource
    IEamCiSvc eamCiSvc;

    @Resource
    ESDictionaryItemSvc dictionaryItemSvc;

    @Resource
    ESDictionaryClassSvc esDictionaryClassSvc;

    @Resource
    private BmConfigSvc bmConfigSvc;

    @Resource
    private ICIRltSwitchSvc iciRltSwitchSvc;

    @Resource
    private PlanDesignInstanceService planInstanceSvc;

    @Resource
    AppPanoramaSvc appPanoramaSvc;
    @Resource
    IEamCIClassApiSvc ciClassApiSvc;


    @Override
    public Page<ESCIInfo>  queryAppSystemList(AppSystemQueryVo queryVo) {
        CcCiClassInfo classIdByCode = getClassIdByCode(Env.HT_APP_SYSTEM.getClassCode());
        if (BinaryUtils.isEmpty(classIdByCode)) {
            return new Page<>();
        }
        Long classId = classIdByCode.getCiClass().getId();
        ESCISearchBean esciSearchBean = new ESCISearchBean();
        esciSearchBean.setClassIds(Collections.singletonList(classId));
        List<ClsAttrQueryGroup> andClsAttrQueryGroups = new ArrayList<>();
        if (!BinaryUtils.isEmpty(queryVo.getLike())) {
            List<String> queryConditions = Env.HT_APP_SYSTEM.getQueryConditions();
            // 查询条件支持 系统名称和系统标识等
            List<ESAttrBean> attrBeans = new ArrayList<>();
            for (String queryCondtion : queryConditions) {
                ESAttrBean esAttrBean = new ESAttrBean();
                esAttrBean.setValue(queryVo.getLike());
                esAttrBean.setOptType(2);
                esAttrBean.setKey(queryCondtion);
                attrBeans.add(esAttrBean);
            }
            ClsAttrQueryGroup likeGroup = new ClsAttrQueryGroup();
            likeGroup.setClassId(classId);
            likeGroup.setOrAttrs(attrBeans);
            andClsAttrQueryGroups.add(likeGroup);
        }
        if (!CollectionUtils.isEmpty(queryVo.getFilters())) {
            for (AppSystemFilterVo filter : queryVo.getFilters()) {
                List<String> params = filter.getParams();
                if (CollectionUtils.isEmpty(params)) {
                    continue;
                }
                List<ESAttrBean> attrBeans = new ArrayList<>();
                for (String param : params) {
                    ESAttrBean esAttrBean = new ESAttrBean();
                    esAttrBean.setValue(param);
                    esAttrBean.setOptType(2);
                    esAttrBean.setKey(filter.getAttrName());
                    attrBeans.add(esAttrBean);
                }
                ClsAttrQueryGroup filterGroup = new ClsAttrQueryGroup();
                filterGroup.setClassId(classId);
                filterGroup.setOrAttrs(attrBeans);
                andClsAttrQueryGroups.add(filterGroup);
            }
        }
        esciSearchBean.setAndClsAttrQueryGroups(andClsAttrQueryGroups);
        esciSearchBean.setPageNum(queryVo.getPageNum());
        esciSearchBean.setPageSize(queryVo.getPageSize());
        // 特殊处理架构决策草稿新建，查询私有库
        Page<ESCIInfo> esciInfoPage = iamsESCIDesignSvc.searchESCIByBean(esciSearchBean);
        if (!CollectionUtils.isEmpty(queryVo.getDecisionCiCodes())) {
            esciSearchBean.setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
            esciSearchBean.setCiCodes(queryVo.getDecisionCiCodes());
            Page<ESCIInfo> privateCIPage = iamsESCIPrivateSvc.searchESCIByBean(esciSearchBean);
            esciInfoPage.getData().addAll(privateCIPage.getData());
        }
        return esciInfoPage;
    }

    @Override
    public CcCiInfo queryAppSystemByCode(String ciCode) {
        Long classId = getClassIdByCode(Env.HT_APP_SYSTEM.getClassCode()).getCiClass().getId();
        CCcCi cdt = new CCcCi();
        cdt.setCiCodeEqual(ciCode);
        cdt.setClassId(classId);
        List<CcCiInfo> ccCiInfos = iamsESCIDesignSvc.queryCiInfoList(cdt, null, Boolean.FALSE, Boolean.TRUE);
        if (CollectionUtils.isEmpty(ccCiInfos)) {
            return null;
        }
        return ccCiInfos.get(0);
    }

    @Override
    public ESCIClassInfo getAppSystemClassInfo() {
        CcCiClassInfo classIdByCode = this.getClassIdByCode(Env.HT_APP_SYSTEM.getClassCode());
        List<ESCIClassInfo> allDefESClassInfosByClassIds = classSvc.getAllDefESClassInfosByClassIds(1L,
                Collections.singletonList(classIdByCode.getCiClass().getId()));
        return allDefESClassInfosByClassIds.get(0);
    }

    @Override
    public String getCardConfiguration() {
        String appSystemConfiguration = Env.HT_APP_SYSTEM.getAppSystemConfiguration();
        List<EamConfiguration> appConfig = iamsEamConfigurationDao.getListByQuery(QueryBuilders.termQuery("type.keyword", appSystemConfiguration));
        if (CollectionUtils.isEmpty(appConfig)) {
            // 返回初始化配置
            EamConfiguration eamConfiguration = new EamConfiguration();
            eamConfiguration.setType(Env.HT_APP_SYSTEM.getAppSystemConfiguration());
            eamConfiguration.setData(Env.HT_APP_SYSTEM.getInitAppSystemConfig());
            iamsEamConfigurationDao.saveOrUpdate(eamConfiguration);
            return Env.HT_APP_SYSTEM.getInitAppSystemConfig();
        }
        return appConfig.get(0).getData();
    }

    @Override
    public void saveCardConfiguration(String data) {
        StringBuilder script = new StringBuilder();
        script.append("ctx._source.data=params.data;");
        Map<String,Object> params = new HashMap<>();
        params.put("data", data);
        iamsEamConfigurationDao.updateByQuery(QueryBuilders.termQuery("type.keyword", Env.HT_APP_SYSTEM.getAppSystemConfiguration()), script.toString(), true, params);
    }

    @Override
    public VcCiClassInfoDto queryAppSystemClassInfo(Long classId, String like) {
        CiQueryCdtExtend cdt = new CiQueryCdtExtend();
        cdt.setClassIds(new Long[]{classId});
        cdt.setLike(like);
        cdt.setViewType("0");
        List<VcCiClassInfoDto> vcCiClassInfoDtos = eamCiSvc.queryCiCountByClass(cdt, LibType.DESIGN);
        if (CollectionUtils.isEmpty(vcCiClassInfoDtos)) {
            throw new BinaryException("应用系统分类信息异常");
        }
        return vcCiClassInfoDtos.get(0);
    }

    public CcCiClassInfo getClassIdByCode(String classCode) {
        CCcCiClass cCcCiClass = new CCcCiClass();
        cCcCiClass.setClassCodeEqual(classCode);
        List<CcCiClassInfo> resultList = classSvc.queryCiClassInfoList(cCcCiClass, null, false);
        if (CollectionUtils.isEmpty(resultList)) {
            return null;
        }
        return resultList.get(0);
    }

    @Override
    public List<AppSystemQueryConVo> getQueryConditions() {
        List<AppSystemQueryConVo> queryConVos = new ArrayList<>();
        String appSystemQueryConditionsJson = bmConfigSvc.getConfigType("SYSTEM_QUERY_CONDITION");
        List<AppSystemQueryCondition> conditions = JSON.parseArray(appSystemQueryConditionsJson, AppSystemQueryCondition.class);
        if (CollectionUtils.isEmpty(conditions)) {
            return queryConVos;
        }
        conditions.sort(Comparator.comparing(AppSystemQueryCondition::getSortNum));
        //获取分类信息
        CcCiClassInfo classIdByCode = this.getClassIdByCode(Env.HT_APP_SYSTEM.getClassCode());
        if (CollectionUtils.isEmpty(classIdByCode.getAttrDefs())) {
            return queryConVos;
        }
        Map<String, CcCiAttrDef> ccCiAttrDefMap = classIdByCode.getAttrDefs().stream().collect(Collectors.toMap(CcCiAttrDef::getProName, e -> e));
        List<AppSystemQueryCondition> fillConditions = conditions.stream()
                .filter(c -> StringUtils.isBlank(c.getCustomer()))
                .filter(c -> ccCiAttrDefMap.containsKey(c.getAttrName())).collect(Collectors.toList());
        Map<String, AppSystemAtrrComm> attrInfo = new ConcurrentHashMap<>();
        List<String> attrNames = fillConditions.stream().map(AppSystemQueryCondition::getAttrName).collect(Collectors.toList());
        //填充字典类型属性查询条件
        this.fillTypeDict(attrInfo, attrNames, ccCiAttrDefMap);
        //填充枚举类型属性查询条件
        fillTypeEnum(attrInfo, attrNames, ccCiAttrDefMap);
        for (AppSystemQueryCondition condition : conditions) {
            if (StringUtils.isNotBlank(condition.getCustomer())) {
                queryConVos.add(new AppSystemQueryConVo(condition.getAttrName(),
                        Collections.singletonList(new AppSystemQueryConParamVo(condition.getCustomer(), null))));
                continue;
            }
            if (!attrInfo.containsKey(condition.getAttrName())) {
                queryConVos.add(new AppSystemQueryConVo(condition.getAttrName(), new ArrayList<>()));
                continue;
            }
            AppSystemAtrrComm appSystemAtrrComm = attrInfo.getOrDefault(condition.getAttrName(), new AppSystemAtrrComm());
            List<AppSystemQueryConParamVo> params = new ArrayList<>();
            switch (appSystemAtrrComm.getOpType()) {
                case 6:
                    for (String value : appSystemAtrrComm.getEnumValues()) {
                        params.add(new AppSystemQueryConParamVo(value, null));
                    }
                    break;
                case 8 :
                    for (ESDictionaryItemInfo itemInfo : appSystemAtrrComm.getDictionaryItems()) {
                        String[] dictionaryAttrDefProNames = appSystemAtrrComm.getDictionaryAttrDefProName().split(CiClassProDropSourceDefHelper.DEF_PRONAME_SEPARATOR);
                        List<String> values = new ArrayList<>();
                        for (String dictionaryAttrDefProName : dictionaryAttrDefProNames) {
                            String value = itemInfo.getAttrs().get(dictionaryAttrDefProName);
                            if (StringUtils.isBlank(value)) {
                                continue;
                            }
                            values.add(value);
                        }
                        if (!CollectionUtils.isEmpty(values)) {
                            String paramName = String.join(CiClassProDropSourceDefHelper.DEF_PRONAME_SEPARATOR, values);
                            params.add(new AppSystemQueryConParamVo(paramName, itemInfo.getAttrs().get("颜色")));
                        }
                    }
                    break;
                default:
                    break;
            }
            queryConVos.add(new AppSystemQueryConVo(condition.getAttrName(), params));
        }
        return queryConVos;
    }

    @Override
    public AppArchWallConfigVo getAppArchWallConfig() {
        AppArchWallConfigVo archWallConfigVo = new AppArchWallConfigVo();
        //获取分类信息
        CcCiClassInfo ccCiClassInfo = this.getClassIdByCode(Env.HT_APP_SYSTEM.getClassCode());
        if (BinaryUtils.isEmpty(ccCiClassInfo)) {
            return archWallConfigVo;
        }
        archWallConfigVo.setClassId(ccCiClassInfo.getCiClass().getId());
        if (CollectionUtils.isEmpty(ccCiClassInfo.getAttrDefs())) {
            return archWallConfigVo;
        }
        String appArchWallConfigJson = bmConfigSvc.getConfigType("SYSTEM_ARCH_WALL_CONFIG");
        AppArchWallConfig appArchWallConfig = JSON.parseObject(appArchWallConfigJson, AppArchWallConfig.class);
        if (appArchWallConfig == null) {
            return archWallConfigVo;
        }
        archWallConfigVo.setTitle(appArchWallConfig.getTitle());
        archWallConfigVo.setIcon(appArchWallConfig.getIcon());
        archWallConfigVo.setDesc(appArchWallConfig.getDesc());
        if (CollectionUtils.isEmpty(appArchWallConfig.getLabels())) {
            return archWallConfigVo;
        }
        Map<String, CcCiAttrDef> ccCiAttrDefMap = ccCiClassInfo.getAttrDefs().stream().collect(Collectors.toMap(CcCiAttrDef::getProName, e -> e));
        List<String> attrNames = appArchWallConfig.getLabels();
        Map<String, AppSystemAtrrComm> attrInfo = new ConcurrentHashMap<>();
        //填充字典类型属性查询条件
        this.fillTypeDict(attrInfo, attrNames, ccCiAttrDefMap);
        //填充枚举类型属性查询条件
        fillTypeEnum(attrInfo, attrNames, ccCiAttrDefMap);
        List<AppArchWallConfigLabelVo> labels = new ArrayList<>();
        AppArchWallConfigLabelVo labelVo;
        for (String attrName : attrNames) {
            labelVo = new AppArchWallConfigLabelVo();
            AppSystemAtrrComm appSystemAtrrComm = attrInfo.getOrDefault(attrName, new AppSystemAtrrComm());
            labelVo.setAttrName(attrName);
            labelVo.setDictClassId(appSystemAtrrComm.getDictClassId());
            List<AppArchWallConfigLabelVo.AttrList> details = new ArrayList<>();
            AppArchWallConfigLabelVo.AttrList detail;
            switch (appSystemAtrrComm.getOpType()) {
                case 6:
                    for (String value : appSystemAtrrComm.getEnumValues()) {
                        detail = new AppArchWallConfigLabelVo.AttrList();
                        detail.setName(value);
                        detail.setColor(null);
                        details.add(detail);
                    }
                    break;
                case 8 :
                    for (ESDictionaryItemInfo itemInfo : appSystemAtrrComm.getDictionaryItems()) {
                        String[] dictionaryAttrDefProNames = appSystemAtrrComm.getDictionaryAttrDefProName().split(CiClassProDropSourceDefHelper.DEF_PRONAME_SEPARATOR);
                        List<String> values = new ArrayList<>();
                        for (String dictionaryAttrDefProName : dictionaryAttrDefProNames) {
                            String value = itemInfo.getAttrs().get(dictionaryAttrDefProName);
                            if (StringUtils.isBlank(value)) {
                                continue;
                            }
                            values.add(value);
                        }
                        if (!CollectionUtils.isEmpty(values)) {
                            String name = String.join(CiClassProDropSourceDefHelper.DEF_PRONAME_SEPARATOR, values);
                            detail = new AppArchWallConfigLabelVo.AttrList();
                            detail.setName(name);
                            detail.setColor(itemInfo.getAttrs().get("颜色"));
                            details.add(detail);
                        }
                    }
                    break;
                default:
                    break;
            }
            labelVo.setDetails(details);
            labels.add(labelVo);
        }
        archWallConfigVo.setLabels(labels);
        return archWallConfigVo;
    }

    /**
     * 填充字典类型属性字段
     * @param attrInfo
     * @param attrNames
     * @param ccCiAttrDefMap
     */
    private void fillTypeDict(Map<String, AppSystemAtrrComm> attrInfo, List<String> attrNames, Map<String, CcCiAttrDef> ccCiAttrDefMap) {
        if (CollectionUtils.isEmpty(attrNames)) {
            return;
        }
        Map<String, Long> attrNameDictMap = new LinkedHashMap<>();
        Map<String, List<Long>> attrNameDictAttrDefMap = new LinkedHashMap<>();
        List<Long> dictClassIds = new ArrayList<>();
        for (String attrName : attrNames) {
            CcCiAttrDef ccCiAttrDef = ccCiAttrDefMap.get(attrName);
            if (ccCiAttrDef.getProType() != 8
                    || StringUtils.isBlank(ccCiAttrDef.getProDropSourceDef())
                    || !ccCiAttrDef.getProDropSourceDef().contains(":")) {
                continue;
            }
            Long dictClassId = CiClassProDropSourceDefHelper.getCiClassProDropSourceClassId(ccCiAttrDef.getProDropSourceDef().trim());
            attrNameDictMap.put(ccCiAttrDef.getProName(), dictClassId);
            Long[] dictAttrDefIds = CiClassProDropSourceDefHelper.getCiClassProDropSourceDefIds(ccCiAttrDef.getProDropSourceDef().trim());
            attrNameDictAttrDefMap.put(ccCiAttrDef.getProName(), Stream.of(dictAttrDefIds).collect(Collectors.toList()));
            dictClassIds.add(dictClassId);
        }
        if (CollectionUtils.isEmpty(dictClassIds)) {
            return;
        }
        //获取字典定义
        List<ESDictionaryClassInfo> dictClassInfos = esDictionaryClassSvc.getListByQuery(QueryBuilders.termsQuery("id", dictClassIds));
        Map<Long, ESDictionaryClassInfo> dictClassInfoMap = dictClassInfos.stream().collect(Collectors.toMap(ESDictionaryClassInfo::getId, e -> e));
        //获取字典数据列表
        List<ESDictionaryItemInfo> dictionaryItemInfos = dictionaryItemSvc.getListByQuery(QueryBuilders.termsQuery("dictClassId", dictClassIds));
        Map<Long, List<ESDictionaryItemInfo>>dictionaryItemMap = dictionaryItemInfos.stream().collect(Collectors.groupingBy(ESDictionaryItemInfo::getDictClassId));
        for (Map.Entry<String, Long> entry : attrNameDictMap.entrySet()) {
            String attrName = entry.getKey();
            Long dictClassId = attrNameDictMap.get(attrName);
            ESDictionaryClassInfo dictClassInfo = dictClassInfoMap.get(dictClassId);
            if (dictClassInfo == null || CollectionUtils.isEmpty(dictClassInfo.getDictAttrDefs())) {
                continue;
            }
            List<ESDictionaryAttrDef> dictAttrDefs = dictClassInfo.getDictAttrDefs();
            Map<Long, ESDictionaryAttrDef> dictionaryAttrDefMap = dictAttrDefs.stream().collect(Collectors.toMap(ESDictionaryAttrDef::getId, e -> e));
            List<Long> dictAttrDefIds = attrNameDictAttrDefMap.get(attrName);
            List<String> dictionaryAttrDefProNames = new ArrayList<>();
            for (Long dictAttrDefId : dictAttrDefIds) {
                if (dictionaryAttrDefMap.containsKey(dictAttrDefId)) {
                    //获取分类字段关联的字段属性
                    ESDictionaryAttrDef attrDef = dictionaryAttrDefMap.get(dictAttrDefId);
                    dictionaryAttrDefProNames.add(attrDef.getProName());
                }
            }
            if (!CollectionUtils.isEmpty(dictionaryAttrDefProNames)) {
                List<ESDictionaryItemInfo> dictionaryItems = dictionaryItemMap.getOrDefault(dictClassId, new ArrayList<>());
                AppSystemAtrrComm appSystemAtrrComm = new AppSystemAtrrComm();
                appSystemAtrrComm.setDictClassId(dictClassId);
                appSystemAtrrComm.setDictionaryAttrDefProName(String.join(CiClassProDropSourceDefHelper.DEF_PRONAME_SEPARATOR, dictionaryAttrDefProNames));
                appSystemAtrrComm.setDictionaryItems(dictionaryItems);
                appSystemAtrrComm.setOpType(8);
                attrInfo.put(attrName, appSystemAtrrComm);
            }
        }
    }

    /**
     * 填充枚举类型属性字段
     * @param attrInfo
     * @param attrNames
     * @param ccCiAttrDefMap
     */
    private void fillTypeEnum(Map<String, AppSystemAtrrComm> attrInfo, List<String> attrNames, Map<String, CcCiAttrDef> ccCiAttrDefMap) {
        if (CollectionUtils.isEmpty(attrNames)) {
            return;
        }
        for (String attrName : attrNames) {
            CcCiAttrDef ccCiAttrDef = ccCiAttrDefMap.get(attrName);
            if (ccCiAttrDef.getProType() != 6) {
                continue;
            }
            List<String> values = new ArrayList<>();
            if (StringUtils.isNotBlank(ccCiAttrDef.getEnumValues())) {
                values = JSON.parseArray(ccCiAttrDef.getEnumValues(), String.class);
            }
            AppSystemAtrrComm appSystemAtrrComm = new AppSystemAtrrComm();
            appSystemAtrrComm.setOpType(6);
            appSystemAtrrComm.setEnumValues(values);
            attrInfo.put(ccCiAttrDef.getProName(), appSystemAtrrComm);
        }
    }

    @Override
    public List<ESCIInfo> getByIds(List<String> ids) {
        Long classId = getClassIdByCode(Env.HT_APP_SYSTEM.getClassCode()).getCiClass().getId();
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("classId", classId));
        query.must(QueryBuilders.termsQuery("ciCode.keyword", ids));
        return iamsESCIDesignSvc.getListByQuery(query);
    }

    @Override
    public List<ESCIInfo> getPrivateByIds(List<String> ids) {
        Long classId = getClassIdByCode(Env.HT_APP_SYSTEM.getClassCode()).getCiClass().getId();
        ESCISearchBean bean = new ESCISearchBean();
        bean.setCiCodes(ids);
        bean.setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
        bean.setDomainId(SysUtil.getCurrentUserInfo().getDomainId());
        bean.setClassIds(Lists.newArrayList(classId));
        bean.setPageSize(3000);
        return iamsESCIPrivateSvc.searchESCIByBean(bean).getData();
    }

    @Override
    public List<AppSystemAssetsVo> getSystemAssets(String ciCode) {
        List<AppSystemAssetsVo> systemAssetsVos = new ArrayList<>();
        List<ESCIInfo> ciList = ciSwitchSvc.getCiByCodes(Collections.singletonList(ciCode), null, LibType.DESIGN);
        if (CollectionUtils.isEmpty(ciList)) {
            return systemAssetsVos;
        }
        ESCIInfo rootCIInfo = ciList.get(0);
        String name = BinaryUtils.isEmpty(rootCIInfo.getCiLabel())?"":rootCIInfo.getCiLabel().replaceAll("[\\[\\]\\\\\"]", "");
        AppSystemAssetsVo rootSystemAssest = AppSystemAssetsVo.builder().code(rootCIInfo.getCiCode()).name(name).value(rootCIInfo).build();
        systemAssetsVos.add(rootSystemAssest);

        ESRltSearchBean esRltSearchBean = new ESRltSearchBean();
        esRltSearchBean.setPageSize(3000);
        esRltSearchBean.setSourceCiCodes(Collections.singleton(ciCode));
        Page<CcCiRltInfo> ccCiRltInfoPage = iciRltSwitchSvc.searchRltByBean(esRltSearchBean, LibType.DESIGN);
        List<CcCiRltInfo> ccCiRltInfos = ccCiRltInfoPage.getData();
        if (CollectionUtils.isEmpty(ccCiRltInfos)){
            return systemAssetsVos;
        }
        List<CcCiInfo> targetCiInfos = ccCiRltInfos.stream().map(CcCiRltInfo::getTargetCiInfo).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(targetCiInfos)) {
            List<Long> emptyTargetCiClassIds = targetCiInfos.stream()
                    .filter(targetCi -> targetCi.getCiClass() == null)
                    .map(targetCi -> targetCi.getCi().getClassId())
                    .distinct().collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(emptyTargetCiClassIds)) {
                List<ESCIClassInfo> esciClassInfos = ciClassApiSvc.selectCiClassByIds(emptyTargetCiClassIds);
                if (!CollectionUtils.isEmpty(esciClassInfos)) {
                    Map<Long, ESCIClassInfo> esciClassInfoMap = esciClassInfos.stream()
                            .collect(Collectors.toMap(ESCIClassInfo::getId, e -> e, (k1,k2) -> k1));
                    for (CcCiInfo targetCiInfo : targetCiInfos) {
                        if (targetCiInfo.getCiClass() != null) {
                            continue;
                        }
                        ESCIClassInfo classInfo = esciClassInfoMap.get(targetCiInfo.getCi().getClassId());
                        if (classInfo != null) {
                            CcCiClass ciClass = new CcCiClass();
                            BeanUtils.copyProperties(classInfo, ciClass);
                            targetCiInfo.setCiClass(ciClass);
                        }
                    }
                }
            }
        }
        Map<String, List<ESCIInfo>> classCodeWithEsCiInfo = new ConcurrentHashMap<>();
        List<CcCiClass> ccCiClasses = new ArrayList<>();
        for (CcCiInfo ccCiInfo : targetCiInfos) {
            CcCiClass ccCiClass = ccCiInfo.getCiClass();
            if (ccCiClass == null) {
                continue;
            }
            //排除目标CI所属分类为根节点CI分类情况
            if (ccCiClass.getId().equals(rootCIInfo.getClassId())) {
                continue;
            }
            if (!classCodeWithEsCiInfo.containsKey(ccCiClass.getClassCode())) {
                ccCiClasses.add(ccCiClass);
            }
            List<ESCIInfo> ciInfos = classCodeWithEsCiInfo.getOrDefault(ccCiClass.getClassCode(), new ArrayList<>());
            ESCIInfo esciInfo = EamUtil.tranESCIInfo(ccCiInfo);
            ciInfos.add(esciInfo);
            classCodeWithEsCiInfo.put(ccCiClass.getClassCode(), ciInfos);
            AppSystemAssetsVo appSystemAssetsVo = AppSystemAssetsVo.builder()
                    .code(esciInfo.getCiCode())
                    .parentCode(ccCiClass.getClassCode())
                    .name(BinaryUtils.isEmpty(esciInfo.getCiLabel())?"":esciInfo.getCiLabel().replaceAll("[\\[\\]\\\\\"]", ""))
                    .value(esciInfo).build();
            systemAssetsVos.add(appSystemAssetsVo);
        }
        for (CcCiClass ccCiClass : ccCiClasses) {
            StringBuilder sb = new StringBuilder()
                    .append(ccCiClass.getClassName())
                    .append("(")
                    .append(classCodeWithEsCiInfo.getOrDefault(ccCiClass.getClassCode(), new ArrayList<>()).size())
                    .append(")");
            AppSystemAssetsVo twoSystemAssest = AppSystemAssetsVo.builder()
                    .code(ccCiClass.getClassCode())
                    .parentCode(ciCode)
                    .name(sb.toString())
                    .value(ccCiClass).build();
            systemAssetsVos.add(twoSystemAssest);
        }
        return systemAssetsVos;
    }

    @Override
    public Page<PlanDesignInstanceDTO> getSystemPlan(Integer pageNum, Integer pageSize, String ciCode) {
        AppPanoramaInfo panoramaInfo = appPanoramaSvc.getPanoramaInfoByCiCode(ciCode);
        List<Long> planIds = Collections.emptyList();
        if (!BinaryUtils.isEmpty(panoramaInfo)) {
             planIds = panoramaInfo.getPlanIds();
        }
        return planInstanceSvc.getSystemPlan(pageNum, pageSize, ciCode,planIds);
    }

    @Override
    public AppSysQueryVo queryAppSystemListNew(AppSystemQueryVo queryVo, LibType libType) {
        BinaryUtils.checkEmpty(queryVo.getClassCode(),"分类classCode不能为空");
        ESCIClassInfo classInfo = ciClassApiSvc.getCIClassByCode(queryVo.getClassCode());
        if(BinaryUtils.isEmpty(classInfo)){
            throw new BinaryException("分类信息不存在，分类标识："+queryVo.getClassCode());
        }
        List<ESCIInfo> allCi = searchCiList(queryVo, libType);
        int skip = (queryVo.getPageNum() - 1) * queryVo.getPageSize();
        List<ESCIInfo> data = allCi.stream().skip(skip).limit(queryVo.getPageSize()).collect(Collectors.toList());
        Page<ESCIInfo> result = new Page<>();
        result.setPageNum(queryVo.getPageNum());
        result.setPageSize(queryVo.getPageSize());
        result.setData(data);
        result.setTotalRows(allCi.size());
        result.setTotalPages((int)Math.ceil(allCi.size() * 1.0 / queryVo.getPageSize()));
        AppSysQueryVo vo = new AppSysQueryVo();
        if(!BinaryUtils.isEmpty(data)){
            vo.setEsciInfo(data);
            vo.setAttrDefs(classInfo.getAttrDefs());
            vo.setPageNum(queryVo.getPageNum());
            vo.setPageSize(queryVo.getPageSize());
            vo.setTotalPages((int)Math.ceil(allCi.size() * 1.0 / queryVo.getPageSize()));
            vo.setTotalRows(allCi.size());
        }
        return vo;
    }
    private List<ESCIInfo> searchCiList(AppSystemQueryVo queryVo, LibType libType) {
        //根据classCode查询分类；
        Long classId = getClassIdByCode(queryVo.getClassCode()).getCiClass().getId();
        ESCISearchBean esciSearchBean = new ESCISearchBean();
        esciSearchBean.setClassIds(Collections.singletonList(classId));
        List<ClsAttrQueryGroup> andClsAttrQueryGroups = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(queryVo.getLikeParams())){
            List<TimeAndLikeQueryParam> filterLikeList = queryVo.getLikeParams().stream().filter(each -> !BinaryUtils.isEmpty(each.getLike())).collect(Collectors.toList());
            if(!BinaryUtils.isEmpty(filterLikeList)){
                // 查询条件支持 系统名称和系统标识等
                List<ESAttrBean> attrBeans = new ArrayList<>();
                for (TimeAndLikeQueryParam param : filterLikeList) {
                    ESAttrBean esAttrBean = new ESAttrBean();
                    esAttrBean.setValue(param.getLike());
                    esAttrBean.setOptType(2);
                    esAttrBean.setKey(param.getAttrName());
                    attrBeans.add(esAttrBean);
                }
                ClsAttrQueryGroup likeGroup = new ClsAttrQueryGroup();
                likeGroup.setClassId(classId);
                likeGroup.setOrAttrs(attrBeans);
                andClsAttrQueryGroups.add(likeGroup);
            }
        }

        if (CollectionUtils.isNotEmpty(queryVo.getFilters())) {
            for (AppSystemFilterVo filter : queryVo.getFilters()) {
                List<String> params = filter.getParams();
                if (CollectionUtils.isEmpty(params)) {
                    continue;
                }
                List<ESAttrBean> attrBeans = new ArrayList<>();
                for (String param : params) {
                    ESAttrBean esAttrBean = new ESAttrBean();
                    esAttrBean.setValue(param);
                    esAttrBean.setOptType(1);
                    esAttrBean.setKey(filter.getAttrName());
                    attrBeans.add(esAttrBean);
                }
                ClsAttrQueryGroup filterGroup = new ClsAttrQueryGroup();
                filterGroup.setClassId(classId);
                filterGroup.setOrAttrs(attrBeans);
                andClsAttrQueryGroups.add(filterGroup);
            }
        }

        if(CollectionUtils.isNotEmpty(queryVo.getTimeParams())){
            List<ESAttrBean> attrBeans = new ArrayList<>();
            for (TimeAndLikeQueryParam param : queryVo.getTimeParams()) {
                if(!BinaryUtils.isEmpty(param.getStartTime())){
                    checkTime(param.getStartTime());
                    ESAttrBean esAttrBean = new ESAttrBean();
                    esAttrBean.setValue(param.getStartTime());
                    esAttrBean.setOptType(6);
                    esAttrBean.setKey(param.getAttrName());
                    attrBeans.add(esAttrBean);
                }
                if(!BinaryUtils.isEmpty(param.getEndTime())){
                    checkTime(param.getEndTime());
                    ESAttrBean esAttrBean = new ESAttrBean();
                    esAttrBean.setValue(param.getEndTime());
                    esAttrBean.setOptType(4);
                    esAttrBean.setKey(param.getAttrName());
                    attrBeans.add(esAttrBean);
                }
            }
            ClsAttrQueryGroup filterGroup = new ClsAttrQueryGroup();
            filterGroup.setClassId(classId);
            filterGroup.setAndAttrs(attrBeans);
            andClsAttrQueryGroups.add(filterGroup);
        }
        esciSearchBean.setAndClsAttrQueryGroups(andClsAttrQueryGroups);
        esciSearchBean.setPageNum(1);
        esciSearchBean.setPageSize(3000);
//        List<SortBuilder<?>> sorts = new ArrayList<>();
//        sorts.add(SortBuilders.fieldSort("modifyTime").order(SortOrder.DESC));
        List<ESCIInfo> allCi = new ArrayList<>();
        if (LibType.PRIVATE.equals(libType)) {
            esciSearchBean.setOwnerCode(SysUtil.getCurrentUserInfo().getLoginCode());
        }
        Page<ESCIInfo> page = ciSwitchSvc.searchESCIByBean(esciSearchBean,libType);
        allCi.addAll(page.getData());
        if (page.getTotalRows() > 3000) {
            for (int i = 2; i < Math.ceil(page.getTotalRows() * 1.0 / 3000); i++) {
                esciSearchBean.setPageNum(i);
                Page<ESCIInfo> pageByQuery = ciSwitchSvc.searchESCIByBean(esciSearchBean, libType);
                if (org.springframework.util.CollectionUtils.isEmpty(pageByQuery.getData())) {
                    break;
                }
                allCi.addAll(pageByQuery.getData());
            }
        }
        Iterator<ESCIInfo> iterator = allCi.iterator();
        List<ESCIInfo> cancellationCiList = new ArrayList<>();
        while (iterator.hasNext()) {
            ESCIInfo next = iterator.next();
            if (!BinaryUtils.isEmpty(next) && CANCELLED.equals(next.getAttrs().get(RELEASE_STATE))) {
                cancellationCiList.add(next);
                iterator.remove();
            }
        }
        allCi.addAll(cancellationCiList);
        return allCi;
    }


    public void checkTime(String time){
        String timeRegex = "^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29))\\s+([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$";
        boolean flag = Pattern.matches(timeRegex, time);
        if(!flag){
            throw new BinaryException("日期格式不正确(yyyy-MM-dd hh:mm:ss)，请检查");
        }
    }

    @Override
    public List<ESCIAttrDefInfo> getDefInfoByClassCode(String classCode) {
        BoolQueryBuilder query = new BoolQueryBuilder();
        query.must(QueryBuilders.termQuery("classCode.keyword",classCode));
        List<ESCIClassInfo> ciClass = classSvc.getListByQuery(query);
        if(BinaryUtils.isEmpty(ciClass)){
            return new ArrayList<>();
        }
        List<ESCIAttrDefInfo> resultDefList = new ArrayList<>();
        List<ESCIAttrDefInfo> ccAttrDefs = ciClass.get(0).getAttrDefs();
        for (ESCIAttrDefInfo ccAttrDef : ccAttrDefs) {
            Integer proType = ccAttrDef.getProType();
            if( proType ==3 || proType == 4 || proType == 6 || proType == 7 || proType == 8 || proType == 11){
                resultDefList.add(ccAttrDef);
            }
        }
        return resultDefList;
    }

    @Override
    public ResponseEntity<byte[]> exportBySearch(AppSystemQueryVo queryVo, LibType libType) {
        queryVo.setPageNum(1);
        queryVo.setPageSize(3000);
        List<ESCIInfo> data = searchCiList(queryVo, libType);
        ExportCiVO exportDto = new ExportCiVO();

        if (org.springframework.util.CollectionUtils.isEmpty(data)) {
            CcCiClassInfo ciClassByCodes = ciClassApiSvc.getCIClassByCodes(queryVo.getClassCode());
            if (BinaryUtils.isEmpty(ciClassByCodes)) {
                throw new BinaryException("分类信息不存在");
            }
            exportDto.setCiClassIds(Sets.newHashSet(ciClassByCodes.getCiClass().getId()));
        } else {
            exportDto.setCiClassIds(Sets.newHashSet(data.get(0).getClassId()));
        }
        // 设置导出字段默认全部导出
//        CcCiClassInfoConfVO attrClassInfo =  listAttrConfSvc.getListShowAttrList(param.getAppSquareConfId(), param.getType());
//        if (!BinaryUtils.isEmpty(attrClassInfo)) {
//            List<Long> attrIdList = new ArrayList<>();
//            List<Long> attrIds = attrClassInfo.getShowListCIAttrInfo().stream().map(ccCiAttrDef -> ccCiAttrDef.getId()).collect(Collectors.toList());
//            attrIdList.addAll(attrIds);
//            List<Long> tagAttrIds = attrClassInfo.getTagListCIAttrInfo().stream().map(ccCiAttrDefConfVO -> ccCiAttrDefConfVO.getId()).collect(Collectors.toList());
//            attrIdList.addAll(tagAttrIds);
//            if (!CollectionUtils.isEmpty(attrIdList)) {
//                HashMap<Long, List<Long>> attrsIdMap = new HashMap<>(1);
//                Set<Long> ciClassIds = exportDto.getCiClassIds();
//                attrsIdMap.put(ciClassIds.toArray(new Long[1])[0], attrIdList);
//                exportDto.setAttrsIdMap(attrsIdMap);
//            }
//        }
        Set<Long> ids = data.stream().map(esciInfo -> esciInfo.getId()).collect(Collectors.toSet());
        exportDto.setHasData(1);
        exportDto.setCiIds(ids);
        exportDto.setHasClsDef(1);
        ResponseEntity<byte[]> responseEntity = ciSwitchSvc.exportCiClassAndAttrs(exportDto, libType);
        return responseEntity;
    }
}
